#include <gui/VkGui.h>
#include <imgui_impl_vulkan.h>
#include <imgui_impl_glfw.h>
#include <gfx/vk/core.h>
#include <gfx/vk/helper.h>

struct
{
    VkCommandBuffer render_buffer;
    VkDescriptorPool desc_pool;
    VkRenderPass render_pass;
}global{};

namespace primal
{
    namespace gui
    {
        PFN_vkVoidFunction imgui_load_vk_function(const char* name, void* user)
        {
            auto ptr = gfx::dev().GetProcAddr(name);
            if(ptr == nullptr)
            {
                ptr = vkGetInstanceProcAddr(gfx::vk_instance(), name);
            }
            return ptr;
        }

        void impl_new_frame()
        {
            ImGui_ImplVulkan_NewFrame();
            ImGui_ImplGlfw_NewFrame();
            ImGui::NewFrame();
        }

        void impl_draw()
        {
            ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), global.render_buffer);
        }

        bool impl_initialize(GLFWwindow *window)
        {
            bool res{ true };

            res &= ImGui_ImplVulkan_LoadFunctions(imgui_load_vk_function, nullptr);
            ImGui_ImplVulkan_InitInfo init_info{};

            init_info.Instance = gfx::vk_instance();
            init_info.PhysicalDevice = gfx::phy();
            init_info.Device = gfx::dev()._dev;
            init_info.QueueFamily = gfx::default_queue_family_index;
            init_info.Queue = gfx::graphics_queue();

            VkDescriptorPoolSize pool_sizes[] =
            {
                { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 },
            };
            VkDescriptorPoolCreateInfo pool_info = {};
            pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
            pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
            pool_info.maxSets = 1;
            pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
            pool_info.pPoolSizes = pool_sizes;
            gfx::dev().CreateDescriptorPool(&pool_info, &global.desc_pool);

            init_info.DescriptorPool = global.desc_pool;
            init_info.Subpass = 0;
            init_info.MinImageCount = 8u;
            init_info.ImageCount = 8u;
            init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;

            res &= ImGui_ImplVulkan_Init(&init_info, gfx::get_pass(gfx::RENDERE_PASS_TYPE::UI));
            res &= ImGui_ImplGlfw_InitForVulkan(window, true);
            return res;
        }

        void gui_impl_shutdown()
        {
            ImGui_ImplVulkan_Shutdown();
            ImGui_ImplGlfw_Shutdown();
        }

        void set_render_comamnd(void* cmd)
        {
            global.render_buffer = static_cast<VkCommandBuffer>(cmd);
        }
    } // namespace gui

} // namespace primal